package com.dz.risk.common;

import com.dz.risk.common.exception.RRException;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author baohao
 * @className 常用工具类
 * @date 2021/1/25 11:33
 */
@Slf4j
public class GeneralUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(GeneralUtils.class);

    public static final int EIGHT = 8;

    /**
     * 生成随机数  时间戳+UUID
     * @param
     * @return
     */
    public static String randomUUID() {
        return System.currentTimeMillis() + UUID.randomUUID().toString().substring(EIGHT).replace("-", "");
    }

    /**
     * 生成随机数  时间戳+UUID
     * @param num
     * @return
     */
    public static String randomUUID(int num) {
        return System.currentTimeMillis() + UUID.randomUUID().toString().substring(num).replace("-", "");
    }

    /**
     * 根据属性名称 获取对应属性值
     * @param fieldName
     * @param object
     * @return
     */
    public static Object getFieldValueByFieldNameValue(String fieldName, Object object) {
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            //对private的属性的访问
            field.setAccessible(true);
            return field.get(object);
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("根据属性名称 获取对应属性值 失败！" + fieldName + "," + object + e.getMessage());
            return null;
        }
    }

    /**
     * 根据属性字段赋值
     * @param obj
     * @param fieldName
     * @param value
     */
    public static void setFieldValueByName(Object obj, String fieldName, Object value) {
        try {
            Field f = obj.getClass().getDeclaredField(fieldName);
            f.setAccessible(true);
            f.set(obj, value);
        } catch (Exception e) {
            LOGGER.error("根据属性字段赋值 失败！" + "," + obj + "," + fieldName + e.getMessage());
        }
    }

    /**
     * 根据对象 获取对应属性名称
     * @return
     */
    public static String getFieldValueByFieldName(int index, Object object) {
        try {
            String name = object.getClass().getDeclaredFields()[index].getName();
            return name;
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("获取对应属性名称 失败！" + "," + object + e.getMessage());
            return null;
        }
    }

    /**
     * 正则验证sql拼接
     **/
    public static String reg = "\\b(and|exec|insert|select|drop|grant|alter|delete|update|count|chr" +
            "|mid|master|truncate|char|declare|or)\\b|(\\*|;|\\+|'|%)\n";

    //b 表示 限定单词边界  比如  select 不通过   1select则是可以的
    public static Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);

    /**
     * sql表名 参数校验，防止sql 注入问题
     * @param str
     * @return
     */
    public static boolean isValidSql(String str) {
        if (!StringUtils.hasLength(str) || sqlPattern.matcher(str).find()) {
            log.error("未能通过过滤器：str=" + str);
            throw new RRException("未能通过过滤器 params:" + str);
        }
        return true;
    }


    /**
     * 功能：驼峰命名转下划线命名
     * 小写和大写紧挨一起的地方,加上分隔符,然后全部转小写
     */
    public static String camel2under(String str) {
        String separator = "_";
        if (str.contains(separator)) {
            return str;
        }
        str = str.replaceAll("([a-z])([A-Z])", "$1" + separator + "$2").toLowerCase();
        return str;
    }


    /**
     * 功能：下划线命名转驼峰命名
     * 将下划线替换为空格,将字符串根据空格分割成数组,再将每个单词首字母大写
     * @param s
     * @return
     */
    private static String under2camel(String s) {
        String separator = "_";
        String under = "";
        s = s.toLowerCase().replace(separator, " ");
        String sarr[] = s.split(" ");
        for (int i = 0; i < sarr.length; i++) {
            String w = sarr[i].substring(0, 1).toUpperCase() + sarr[i].substring(1);
            under += w;
        }
        return under;
    }

}
